package com.cqq.auth.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cqq.auth.dao.ResourceMenuDao;
import com.cqq.auth.dao.ResourceUrlDao;
import com.cqq.auth.dao.UserMenuDao;
import com.cqq.auth.dao.domain.ResourceMenu;
import com.cqq.auth.dao.domain.ResourceUrl;
import com.cqq.auth.dao.domain.UserMenu;
import com.cqq.auth.service.PermResourceService;
import com.cqq.auth.service.PermissionService;
import com.cqq.auth.service.bean.MenuBean;
import com.cqq.auth.service.bean.PermissionBean;
import com.cqq.auth.service.bean.UrlBean;
import com.cqq.auth.service.exception.PermResourceServiceException;
import com.cqq.common.core.base.BaseService;
import com.cqq.common.core.constant.CommonMessage;
import com.cqq.common.core.util.BeanUtil;

@Service("permResourceService")
public class PermResourceServiceImpl extends BaseService implements PermResourceService {

	private static final Logger log = LoggerFactory.getLogger(PermResourceServiceImpl.class);
	
	@Autowired
	private PermissionService permissionService;
	
	@Autowired
	private ResourceMenuDao resourceMenuDao;

	@Autowired
	private ResourceUrlDao resourceUrlDao;
	
	@Autowired
	private UserMenuDao userMenuDao;
	
	
	public void addMenu(MenuBean menu) throws PermResourceServiceException {
		log.debug("addMenu ...");
		if(menu==null || StringUtils.isBlank(menu.getSystemCode())
				|| StringUtils.isBlank(menu.getName())){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		if(menu.getParentId()!=null && !menu.getParentId().equals(0)){
			ResourceMenu parentMenu=resourceMenuDao.queryById(menu.getParentId());
			if(parentMenu==null){
				throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_ERROR));
			}
		}
		ResourceMenu m=BeanUtil.copy(menu, ResourceMenu.class);
		this.resourceMenuDao.add(m);
		menu.setId(m.getId());
		log.debug("addMenu ok! {}",menu);
	}

	
	public void updateMenu(MenuBean menu) throws PermResourceServiceException {
		log.debug("updateMenu ...");
		if(menu==null || menu.getId()==null
				|| StringUtils.isBlank(menu.getSystemCode())
				|| StringUtils.isBlank(menu.getName())){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		if(menu.getParentId()!=null && !menu.getParentId().equals(0)){
			ResourceMenu parentMenu=resourceMenuDao.queryById(menu.getParentId());
			if(parentMenu==null){
				throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_ERROR));
			}
		}
		ResourceMenu m=BeanUtil.copy(menu, ResourceMenu.class);
		this.resourceMenuDao.update(m);
		log.debug("updateMenu ok! {}",menu);
	}

	
	public void deleteMenu(Integer id) throws PermResourceServiceException {
		log.debug("deleteMenu ...");
		if(id==null){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		if(this.resourceMenuDao.delete(id)!=1){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_DELETE_ERROR));
		}
		log.debug("deleteMenu ok! id:{}",id);
	}

	
	public MenuBean findMenuByUrl(String url, String systemCode) {
		if(StringUtils.isBlank(url) || StringUtils.isBlank(systemCode)){
			return null;
		}
		ResourceMenu menu=this.resourceMenuDao.queryByUrl(url, systemCode);
		MenuBean bean=BeanUtil.copy(menu, MenuBean.class);
		return bean;
	}
	
	
	public List<MenuBean> listMenu(Integer userId, String systemCode) {
		return listMenu(userId, systemCode, false);
	}

	
	public List<MenuBean> listMenu(Integer userId, String systemCode,
			Boolean needAll) {
		if(userId==null || StringUtils.isBlank(systemCode)){
			return null;
		}
		if(needAll==null){
			needAll=false;
		}
		List<ResourceMenu> menus=this.resourceMenuDao.queryByUserId(userId, systemCode);
		List<MenuBean> beans=BeanUtil.copyList(menus, MenuBean.class);
		List<UserMenu> userMenus=this.userMenuDao.queryByUserId(userId, systemCode);
		Map<Integer,UserMenu> userMenuMap=new HashMap<Integer,UserMenu>();
		for(UserMenu um:userMenus){
			userMenuMap.put(um.getMenuId(), um);
		}
		
		List<MenuBean> result=new ArrayList<MenuBean>();
		for(MenuBean bean:beans){
			UserMenu um=userMenuMap.get(bean.getId());
			if(um==null){
				result.add(bean);
			}
			else if(um.getNeedShow()==true || needAll){
				bean.setIndex(um.getIndex());
				bean.setNeedShow(um.getNeedShow());
				result.add(bean);
			}
		}
		
		Collections.sort(result,new Comparator<MenuBean>(){
			
			public int compare(MenuBean menu1, MenuBean menu2) {
				return (menu1.getParentId() - menu2.getParentId())*1000 + (menu1.getIndex() - menu2.getIndex());
			}
		});
		
		Map<Integer,List<MenuBean>> menuMap=new HashMap<Integer,List<MenuBean>>();
		List<MenuBean> menuList=null;
		for(MenuBean bean:result){
			menuList=menuMap.get(bean.getParentId());
			if(menuList==null){
				menuList=new ArrayList<MenuBean>();
				menuMap.put(bean.getParentId(), menuList);
			}
			menuList.add(bean);
		}
		
		result=menuMap.get(0);
		this.buildMenuChildren(result, menuMap);		
		return result;
	}
	
	private void buildMenuChildren(List<MenuBean> menuList, Map<Integer,List<MenuBean>> menuMap){
		if(menuList==null){
			return;
		}
		for(MenuBean bean:menuList){
			List<MenuBean> menus=menuMap.get(bean.getId());
			bean.setChildren(menus);
			this.buildMenuChildren(menus, menuMap);
		}
	}
	
	
	public void addUrl(UrlBean url) throws PermResourceServiceException {
		log.debug("addUrl ...");
		if(url==null || StringUtils.isBlank(url.getSystemCode())
				|| StringUtils.isBlank(url.getName())
				|| StringUtils.isBlank(url.getUrl())){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		if(url.getParentId()!=null && !url.getParentId().equals(0)){
			ResourceUrl parentUrl=resourceUrlDao.queryById(url.getParentId());
			if(parentUrl==null){
				throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_ERROR));
			}
		}
		
		ResourceUrl u=BeanUtil.copy(url, ResourceUrl.class);
		this.resourceUrlDao.add(u);
		url.setId(u.getId());
		log.debug("addUrl ok! {}",url);
	}

	
	public void updateUrl(UrlBean url) throws PermResourceServiceException {
		log.debug("updateUrl ...");
		if(url==null || url.getId()==null
				|| StringUtils.isBlank(url.getSystemCode())
				|| StringUtils.isBlank(url.getName())
				|| StringUtils.isBlank(url.getUrl())){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		if(url.getParentId()!=null && !url.getParentId().equals(0)){
			ResourceUrl parentUrl=resourceUrlDao.queryById(url.getParentId());
			if(parentUrl==null){
				throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_ERROR));
			}
		}
		
		ResourceUrl u=BeanUtil.copy(url, ResourceUrl.class);
		this.resourceUrlDao.update(u);
		log.debug("updateUrl ok! {}",url);
	}

	
	public void deleteUrl(Integer id) throws PermResourceServiceException {
		log.debug("deleteUrl ...");
		if(id==null){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		if(this.resourceUrlDao.delete(id)!=1){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_DELETE_ERROR));
		}
		log.debug("deleteUrl ok! id:{}",id);
	}

	
	public List<UrlBean> listAllUrl(String systemCode) {
		if(StringUtils.isBlank(systemCode)){
			return null;
		}
		List<PermissionBean> perms=this.permissionService.listAllPermission(systemCode);
		Map<Integer,PermissionBean> permMap=new HashMap<Integer,PermissionBean>();
		for(PermissionBean perm:perms){
			permMap.put(perm.getId(), perm);
		}
		
		List<ResourceUrl> urls=this.resourceUrlDao.queryAllBySystem(systemCode);
		List<UrlBean> beanList=new ArrayList<UrlBean>();
		for(ResourceUrl url:urls){
			UrlBean bean=BeanUtil.copy(url, UrlBean.class);
			beanList.add(bean);
			if(url.getPermIds()==null || url.getPermIds().length==0){
				continue;
			}
			perms=new ArrayList<PermissionBean>();
			for(Integer id:url.getPermIds()){
				PermissionBean perm=permMap.get(id);
				if(perm==null){
					continue;
				}
				perms.add(perm);
			}
			bean.setPerms(perms);
		}
		return beanList;
	}

	
	public void saveUserMenuConfig(Integer userId, List<MenuBean> menus,String systemCode)
			throws PermResourceServiceException {
		log.debug("saveUserMenuConfig ...");
		if(userId==null || menus==null || menus.isEmpty()
				|| StringUtils.isBlank(systemCode)){
			throw super.buildException(new PermResourceServiceException(CommonMessage.COMMON_PARAM_EMPTY));
		}
		for (MenuBean menuBean : menus) {
			UserMenu menu=userMenuDao.queryByUserIdAndMenuId(userId, menuBean.getId());
			if(menu==null){
				menu=new UserMenu();
				menu.setIndex(menuBean.getIndex());
				menu.setMenuId(menuBean.getId());
				menu.setUserId(userId);
				menu.setSystemCode(systemCode);
				menu.setNeedShow(menuBean.getNeedShow());
				userMenuDao.add(menu);
			}else{
				menu.setIndex(menuBean.getIndex());
				menu.setNeedShow(menuBean.getNeedShow());
				userMenuDao.update(menu);
			}
		}
		/*List<ResourceMenu> userMenus=this.resourceMenuDao.queryByUserId(userId, systemCode);
		Map<Integer,List<ResourceMenu>> menuMap=new HashMap<Integer,List<ResourceMenu>>();
		List<ResourceMenu> menuList=null;
		for(ResourceMenu menu:userMenus){
			menuList=menuMap.get(menu.getParentId());
			if(menuList==null){
				menuList=new ArrayList<ResourceMenu>();
				menuMap.put(menu.getParentId(), menuList);
			}
			menuList.add(menu);
		}
		
		Set<Integer> pidSet=new HashSet<Integer>();
		Map<Integer,UserMenu> userMenuMap=new HashMap<Integer,UserMenu>();
		Map<Integer,Integer> maxIndexMap=new HashMap<Integer,Integer>();
		for(MenuBean menu:menus){
			if(menu.getId()==null
					|| menu.getIndex()==null
					|| menu.getNeedShow()==null
					|| menu.getParentId()==null){
				continue;
			}
			if(pidSet.contains(menu.getParentId())){
				continue;
			}
			pidSet.add(menu.getParentId());
			List<UserMenu> ltUm=this.userMenuDao.queryByUserIdAndParentId(userId, menu.getParentId(), systemCode);
			Integer maxIndex=0;
			for(UserMenu um:ltUm){
				userMenuMap.put(um.getMenuId(), um);
				maxIndex = um.getIndex() > maxIndex ? um.getIndex() : maxIndex;
			}
			
			menuList=menuMap.get(menu.getParentId());
			if(menuList==null || menuList.isEmpty()){
				this.userMenuDao.deleteByUserIdAndParentId(userId, menu.getParentId(), systemCode);
				continue;
			}
			for(ResourceMenu m:menuList){
				if(userMenuMap.containsKey(m.getId())){
					continue;
				}
				UserMenu um=new UserMenu();
				um.setSystemCode(systemCode);
				um.setUserId(userId);
				um.setMenuId(m.getId());
				um.setIndex(m.getIndex());
				um.setNeedShow(m.getNeedShow());
				this.userMenuDao.add(um);
				userMenuMap.put(um.getMenuId(), um);
				maxIndex = um.getIndex() > maxIndex ? um.getIndex() : maxIndex;
			}
			maxIndexMap.put(menu.getParentId(), maxIndex);
		}
		
		if(menus.size()==1){
			MenuBean menu=menus.get(0);
			UserMenu um=userMenuMap.get(menu.getId());
			if(um!=null && (!um.getIndex().equals(menu.getIndex()) || !um.getNeedShow().equals(menu.getNeedShow()))){
				Integer oldIndex=um.getIndex();
				if(menu.getIndex() > oldIndex){
					Integer maxIndex=maxIndexMap.get(menu.getParentId());
					if(menu.getIndex() > maxIndex){
						menu.setIndex(maxIndex);
					}
				}
				um.setIndex(menu.getIndex());
				um.setNeedShow(menu.getNeedShow());
				this.userMenuDao.update(um);
				if(!oldIndex.equals(menu.getIndex())){
					this.userMenuDao.updateIndex(userId, menu.getParentId(), systemCode, menu.getId(), menu.getIndex(), oldIndex);
				}
			}
		}
		else{
			for(MenuBean menu:menus){
				UserMenu um=userMenuMap.get(menu.getId());
				if(um!=null && (!um.getIndex().equals(menu.getIndex()) || !um.getNeedShow().equals(menu.getNeedShow()))){
					um.setIndex(menu.getIndex());
					um.setNeedShow(menu.getNeedShow());
					this.userMenuDao.update(um);
				}
			}
		}*/
		log.debug("saveUserMenuConfig ok! userId:{},menus:{},systemCode:{}",userId,menus,systemCode);
	}


	public static void main(String[] args){
		List<MenuBean> result=new ArrayList<MenuBean>();
		MenuBean m1=new MenuBean();
		m1.setId(1);
		m1.setParentId(0);
		m1.setIndex(-8);
		
		MenuBean m2=new MenuBean();
		m2.setId(2);
		m2.setParentId(0);
		m2.setIndex(-10);
		
		MenuBean m3=new MenuBean();
		m3.setId(3);
		m3.setParentId(2);
		m3.setIndex(-12);
		
		MenuBean m4=new MenuBean();
		m4.setId(4);
		m4.setParentId(1);
		m4.setIndex(-9);
		
		MenuBean m5=new MenuBean();
		m5.setId(5);
		m5.setParentId(2);
		m5.setIndex(-9);
		
		result.add(m3);
		result.add(m1);
		result.add(m4);
		result.add(m2);
		result.add(m5);
		
		Collections.sort(result,new Comparator<MenuBean>(){
			
			public int compare(MenuBean menu1, MenuBean menu2) {
				int i=(menu1.getParentId() - menu2.getParentId())*1000 + (menu1.getIndex() - menu2.getIndex());
				System.out.println(i);
				return i;
			}
		});
		
		log.debug("{}",result);
	}

}
